package cn.noerdenfit;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class Main {

    public static void main(String[] args) throws IOException {
        String projectDir = "F:\\NOERDEN\\project\\source\\i18n\\noerdenfit_android\\NoerdenApp_Android";
//        projectDir = "F:\\NOERDEN\\project\\source\\life2\\noerdenfit_android\\NoerdenApp_Android";
//        projectDir = "F:\\User\\workspace\\I18nDemo";

//        doCleanResource(projectDir);
        restoreResource(projectDir);
    }

    private static void restoreResource(String projectDir) throws IOException {
        final File mergeDir = new File(projectDir, "i18nAppLanguage");
        final File restoreDir = new File(projectDir, "i18nRestoreDir");
        if (restoreDir.exists()) {
            FileUtils.forceDelete(restoreDir);
        }
        if (!restoreDir.exists()) {
            restoreDir.mkdirs();
        }

        //each language
        File[] mergeEachLanguages = mergeDir.listFiles();
        for (File item : mergeEachLanguages) {
            restoreFiles(item, restoreDir);
        }

    }

    private static void restoreFiles(File eachLanguageValue, File restoreDir) throws IOException {
        File xmlFile = new File(eachLanguageValue, "merge_strings.xml");

        LogHelper.info("deal xmlFile=%s", eachLanguageValue);

        String cleanContent = FileUtils.readFileToString(xmlFile, "utf-8");
        cleanContent = cleanContent.replaceAll("<\\?xml[\\s\\S]*?<resources>([\\s\\S]*)</resources>", "$1");
        cleanContent = cleanContent.replaceAll("<resources>([\\s\\S]*)</resources>", "$1");

        final String EACH_FILE_SPLIT = "<!-- ==========EACH-FILE-SPLIT========== -->";
        String[] splitFiles = cleanContent.split(EACH_FILE_SPLIT);
        for (String eachFile : splitFiles) {
            if (eachFile.trim().equals("")) {
                continue;
            }

            String moduleDir = eachFile.replaceAll("[\\s\\S]*\\[MODULE_DIR:(.*?)][\\s\\S]*", "$1");
            String languageDir = eachFile.replaceAll("[\\s\\S]*\\[LANGUAGE_DIR:(.*?)][\\s\\S]*", "$1");
            String filename = eachFile.replaceAll("[\\s\\S]*\\[FILENAME:(.*?)][\\s\\S]*", "$1");
            LogHelper.info("----deal moduleDir=%s, languageDir=%s, filename=%s", moduleDir, languageDir, filename);

            File mDir = new File(restoreDir, moduleDir + "\\" + languageDir);
            if (!mDir.exists()) {
                mDir.mkdirs();
            }

            String s1 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>";
            String s2 = "\r\n</resources>\r\n";
            File sFile = new File(mDir, filename);
            FileUtils.writeStringToFile(sFile, s1, "utf-8", false);
            FileUtils.writeStringToFile(sFile, eachFile, "utf-8", true);
            FileUtils.writeStringToFile(sFile, s2, "utf-8", true);
        }
    }

    private static void doCleanResource(String projectDir) throws IOException {
        //find all include module
        final List<String> allIncludeModule = findAllIncludeModule(projectDir);
        debugInfo(allIncludeModule);

        final File dstDir = new File(projectDir, "i18nResource");
        if (dstDir.exists()) {
            FileUtils.deleteDirectory(dstDir);
        }

        //queue do each module resource
        for (String moduleItem : allIncludeModule) {
            dealEachModule(projectDir, moduleItem);
        }

        //merge all file
        mergeAllFiles(projectDir);
    }

    private static void mergeAllFiles(String projectDir) throws IOException {
        LogHelper.info("-------------------------------");
        LogHelper.info("-------------------------------");
        LogHelper.info("------------Start mergeAllFiles -------------------");
        final File dstDir = new File(projectDir, "i18nResource");
        File[] moduleFiles = dstDir.listFiles();
        if (moduleFiles == null) {
            return;
        }

        final File mergeDir = new File(dstDir.getParent(), "i18nMerge");
        if (mergeDir.exists()) {
            FileUtils.deleteDirectory(mergeDir);
        }

        if (!mergeDir.exists()) {
            mergeDir.mkdirs();
        }

        //"values-zh"-->"merge_file"
        Map<String, File> mulLanguageStrings = new HashMap<>();
        for (File moduleItem : moduleFiles) {
            File[] mulLangValuesFiles = moduleItem.listFiles();
            if (mulLangValuesFiles == null) {
                continue;
            }
            LogHelper.info("------------deal module[%s]----------", moduleItem.getName());
            for (File valueEach : mulLangValuesFiles) {
                addToOneFile(mulLanguageStrings, valueEach, mergeDir, moduleItem);
            }

        }

        Set<String> keySet = mulLanguageStrings.keySet();
        for (String keyItem : keySet) {
            File mergeFile = mulLanguageStrings.get(keyItem);
            String s1 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>";
            String s2 = "\r\n</resources>\r\n";
            String fileToString = FileUtils.readFileToString(mergeFile, "utf-8");
            String newContent = s1 + fileToString + s2;
            FileUtils.writeStringToFile(mergeFile, newContent, "utf-8", false);
            LogHelper.info("处理最后合成步骤：%s", mergeFile.getAbsolutePath());
        }

    }

    private static void addToOneFile(Map<String, File> mulLanguageStrings, File valueEach, File mergeDir, File moduleItem) throws IOException {
        if (valueEach == null) {
            return;
        }
        LogHelper.info("addToOneFile(). deal dir(KEY)=%s, mergeDir=%s", valueEach.getName(), mergeDir.getAbsolutePath());

        File[] eachStrings = valueEach.listFiles();
        if (eachStrings == null) {
            return;
        }

        final String KEY = valueEach.getName();
        File sLanguageDir = new File(mergeDir, KEY);
        if (!sLanguageDir.exists()) {
            sLanguageDir.mkdirs();
        }
        File mergeStringFile = mulLanguageStrings.get(KEY);
        if (mergeStringFile == null) {
            final String MERGE_FILE = "merge_strings.xml";
            mergeStringFile = new File(sLanguageDir, MERGE_FILE);
            mulLanguageStrings.put(KEY, mergeStringFile);
        }


        for (File stringItem : eachStrings) {
            LogHelper.info("mergeing %s", stringItem.getAbsolutePath());

            String startFlag = String.format("\r\n<!-- ==========[MODULE_DIR:%s] [LANGUAGE_DIR:%s] [FILENAME:%s] START========= -->\r\n",
                    moduleItem.getName(), KEY, stringItem.getName());
            FileUtils.writeStringToFile(mergeStringFile, startFlag, "utf-8", true);
            String fileContent = FileUtils.readFileToString(stringItem, "utf-8");
            fileContent = fileContent.replaceAll("<\\?xml[\\s\\S]*?<resources>([\\s\\S]*)</resources>", "$1");
            fileContent = fileContent.replaceAll("<resources>([\\s\\S]*)</resources>", "$1");
            FileUtils.writeStringToFile(mergeStringFile, fileContent, "utf-8", true);
            String endFlag = String.format("\r\n<!-- ==========%s/%s END========= -->\r\n", moduleItem.getName(), KEY);
            FileUtils.writeStringToFile(mergeStringFile, endFlag, "utf-8", true);
            final String EACH_FILE_SPLIT = "\r\n<!-- ==========EACH-FILE-SPLIT========== -->\r\n";
            FileUtils.writeStringToFile(mergeStringFile, EACH_FILE_SPLIT, "utf-8", true);
        }
    }

    private static void dealEachModule(String projectDir, String moduleItem) throws IOException {
        final File dstDir = new File(projectDir, "i18nResource");
        if (!dstDir.exists()) {
            dstDir.mkdirs();
        }
        final File dstDirModule = new File(dstDir, moduleItem);
        if (!dstDirModule.exists()) {
            dstDirModule.mkdirs();
        }

        final File moduleFile = new File(projectDir, moduleItem);
        final List<File> eachValues = obtainValuesRes(moduleFile);
        debugEachValues(eachValues, moduleItem);
        dealEachValueString(dstDirModule, moduleItem, eachValues);
    }

    private static void dealEachValueString(File dstDirModule, String moduleItem, List<File> eachValues) throws IOException {
        for (File item : eachValues) {
            if (item.isDirectory()) {
                File[] resfiles = item.listFiles();
                if (resfiles == null) {
                    continue;
                }

                for (File xmlItem : resfiles) {
                    if (xmlItem.isFile()) {
                        if (xmlItem.getName().endsWith(".xml")) {
                            boolean isContainString = isContainString(xmlItem);
                            if (isContainString) {
                                LogHelper.info("deal xml file: %s", xmlItem.getAbsolutePath());

//                                renameXmlFileSuffixModuleName(xmlItem, moduleItem);

                                final File dstCopyValueFile = new File(dstDirModule, item.getName());
                                final File dstCopyFile = new File(dstCopyValueFile, xmlItem.getName());
                                FileUtils.copyFile(xmlItem, dstCopyFile);
                                dealEachStringFile2(dstCopyFile);

                            }
                        }
                    }
                }
            }
        }
    }

    private static void renameXmlFileSuffixModuleName(File xmlItem, String moduleItem) {
        if (xmlItem.isFile()) {
            String name = xmlItem.getName();
            if (!name.startsWith(moduleItem)) {
                String newName = moduleItem + "_" + name;
                File fNewName = new File(xmlItem.getParent(), newName);
                boolean renameTo = xmlItem.renameTo(fNewName);
                if (!renameTo) {
                    LogHelper.error("重命名失败: %s->%s", name, newName);
                }
            }
        }
    }

    private static void dealEachStringFile2(File dstCopyFile) throws IOException {
        String fileContent = FileUtils.readFileToString(dstCopyFile, "utf-8");
        //clear \n
//        fileContent = fileContent.replaceAll("([^\\\\])\\\\n", "$1\r\n");

        //clear html
//        fileContent = fileContent.replaceAll("\\s*<!\\[CDATA\\[([\\s\\S]*?)]]>\\s*", "$1".trim().replaceAll("\r\n", ""));

        //clear ' char
//        fileContent = fileContent.replaceAll("([^\\\\])\\\\([^\\\\])", "$1$2");

        //clear empty string
//        fileContent = fileContent.replaceAll("(<string .*?)>(\\s*)(</string>)", "$1/>");
        fileContent = fileContent.replaceAll("(<string.*?\".*?\"\\s*)>\\s*</string>", "$1/>");

        //clear redundancy blank
//        fileContent = fileContent.replaceAll("([^(resources|string)]>)(\\s*)(.*?)(\\s*)(</string>)", "$1$3$5");

        FileUtils.write(dstCopyFile, fileContent, "utf-8", false);
    }

    private static boolean isContainString(File item) throws IOException {
        boolean is = false;
        final String content = FileUtils.readFileToString(item, "utf-8");
        if (content.contains("</string>") || content.contains("</string-array>")) {
            is = true;
        }

        return is;
    }

    private static void debugEachValues(List<File> eachValues, String moduleItem) {
        LogHelper.info("\n--------DEBUG [%s] VALUES-----", moduleItem);
        for (File item : eachValues) {
            LogHelper.info("--------values:%s", item.getName());
        }
    }

    private static List<File> obtainValuesRes(File moduleFile) {
        final List<File> valueList = new ArrayList<>();
        File resDir = new File(moduleFile, "res");

        if (!resDir.exists()) {
            resDir = new File(moduleFile, "src\\main\\res");
        }

        if (!resDir.exists()) {
            LogHelper.error("Can not find Resource Dir. Please check it. Path=" + resDir.getAbsolutePath());
            return valueList;
        }

        File[] resSubs = resDir.listFiles();
        if (resSubs == null) {
            LogHelper.error("ResSubs.listFiles is null. Path=" + resDir.getAbsolutePath());
            return valueList;
        }

        for (File item : resSubs) {
            if (item.getName().startsWith("values")) {
                valueList.add(item);
            }
        }

        return valueList;
    }

    private static void debugInfo(List<String> allIncludeModule) {
        LogHelper.info("\n------DEBUG MODULE ITEM-----------");
        for (String item : allIncludeModule) {
            LogHelper.info("item=" + item);
        }
    }

    private static List<String> findAllIncludeModule(String projectDir) throws IOException {
        final List<String> list = new ArrayList<>();
        final String settingFile = "settings.gradle";
        final File file = new File(projectDir, settingFile);
        final String fileConfig = FileUtils.readFileToString(file, "utf-8");

        String cleanContent = fileConfig.replaceAll("^include(\\s\\S)*", "$1");
        String[] modules = cleanContent.split(",");
        for (String item : modules) {
            list.add(item.replaceAll(":", "").replaceAll("'", "").replaceAll("\r\n", "").trim());
        }

        return list;
    }

}
